package render

import (
	"MetroBuilderGameJam/gameEngine/drawer"
	"MetroBuilderGameJam/gameEngine/geom"
	"MetroBuilderGameJam/gameEngine/utils"
	"MetroBuilderGameJam/world"
	"github.com/hajimehoshi/ebiten/v2"
)

func NewBranch(d *drawer.Drawer, endingLength, endingCrossLength, lineWidth float64) *Branch {
	return &Branch{
		drawer:            d,
		offsetter:         newSlotOffsetCalculator(lineWidth),
		endingLength:      endingLength,
		endingCrossLength: endingCrossLength,
		lineWidth:         lineWidth,
	}
}

type Branch struct {
	endingLength      float64
	endingCrossLength float64
	lineWidth         float64
	drawer            *drawer.Drawer
	offsetter         *slotOffsetCalculator
}

func (b *Branch) Draw(screen *ebiten.Image, item world.RailRoadBranch) *utils.Figure {
	if brEnding, ok := item.(*world.BranchEdge); ok {
		return b.DrawEnding(screen, brEnding)
	}

	if item.From() == nil || item.To() == nil {
		return utils.NoFigure()
	}
	from := (*item.From()).AsVec2().Add(b.offsetter.getFromOffset(item)).AsPoint()
	to := (*item.To()).AsVec2().Add(b.offsetter.getToOffset(item)).AsPoint()
	if item.IsInversed() {
		from, to = to, from
	}

	color := item.RailRoad().GetColor()
	if _, ok := item.(*world.BranchRemembered); ok {
		color = drawer.ColorTransparent(color, 0.3)
	}
	line := b.drawer.BendedLine(screen, from, to, b.lineWidth, color)
	if _, ok := item.(*world.BranchProject); ok {
		return utils.NoFigure()
	}
	return utils.NewFigure(item, line)
}

func (b *Branch) DrawEnding(screen *ebiten.Image, ending *world.BranchEdge) *utils.Figure {
	if b.isSecondEndingInLoopRoad(ending) {
		return utils.NoFigure()
	}
	from := *ending.From()
	to := b.calcToPointForEnding(ending)
	//fmt.Println("Draw ending", from, to)
	cross := to.AsVec2().Sub(from.AsVec2()).Normalize().Rotate(geom.Degrees(90).ToRadians())
	crossFrom := to.AsVec2().Add(cross.Mul(b.endingCrossLength)).AsPoint()
	crossTo := to.AsVec2().Sub(cross.Mul(b.endingCrossLength)).AsPoint()

	return utils.NewFigure(
		ending,
		geom.NewColliderSet(
			b.drawer.BendedLine(screen, from, to, b.lineWidth, ending.RailRoad().GetColor()),
			b.drawer.BendedLine(screen, crossFrom, crossTo, b.lineWidth, ending.RailRoad().GetColor()),
		),
	)
}

func (b *Branch) isSecondEndingInLoopRoad(ending *world.BranchEdge) bool {
	return ending.RailRoad().IsLoop() && ending.GetBaseBranch() == ending.RailRoad().GetLastEdge().GetBaseBranch()
}

func (b *Branch) calcToPointForEnding(ending *world.BranchEdge) geom.Point {
	dir := ending.To().AsVec2().Sub(ending.From().AsVec2()).Normalize().Mul(b.endingLength)
	return ending.From().AsVec2().Add(dir).AsPoint()
}
